//
//  AnyJsonObject.swift
//  unit_json
//
//  Created by Yun Zeng on 2018/5/2.
//  Copyright © 2018 Adai.Design. All rights reserved.
//

import Foundation

public protocol JSONType: Codable {
    var jsonValue: Any {get}
}

extension Int: JSONType {
    public var jsonValue: Any {
        return self
    }
}

extension String: JSONType {
    public var jsonValue: Any {
        return self
    }
}

extension Double: JSONType {
    public var jsonValue: Any {
        return self
    }
}

extension Bool: JSONType {
    public var jsonValue: Any {
        return self
    }
}

// 任意JSON格式对象
public struct AnyJSONType: JSONType {
    public var jsonValue: Any
    
    init(_ value: JSONType) {
        jsonValue = value
    }
    
    public func encode(to encoder: Encoder) throws {
        var contaienr = encoder.singleValueContainer()
        if let value = jsonValue as? Bool {
            try contaienr.encode(value)
        } else if let value = jsonValue as? Int {
            try contaienr.encode(value)
        } else if let value = jsonValue as? String {
            try contaienr.encode(value)
        } else if let value = jsonValue as? Double {
            try contaienr.encode(value)
        } else if let value = jsonValue as? Array<AnyJSONType> {
            try contaienr.encode(value)
        } else if let value = jsonValue as? Dictionary<String, AnyJSONType> {
            try contaienr.encode(value)
        } else {
            throw EncodingError.invalidValue(jsonValue,
                    EncodingError.Context(codingPath: encoder.codingPath, debugDescription: "unsupported json format type"))
        }
    }
    
    public init(from decoder: Decoder) throws {
        let container = try decoder.singleValueContainer()
        
        if let intValue = try? container.decode(Int.self) {
            jsonValue = intValue
        } else if let stringValue = try? container.decode(String.self) {
            jsonValue = stringValue
        } else if let boolValue = try? container.decode(Bool.self) {
            jsonValue = boolValue
        } else if let doubleValue = try? container.decode(Double.self) {
            jsonValue = doubleValue
        } else if let arrayValue = try? container.decode(Array<AnyJSONType>.self) {
            jsonValue = arrayValue
        } else if let dictionaryValue = try? container.decode(Dictionary<String, AnyJSONType>.self) {
            jsonValue = dictionaryValue
        } else {
            throw DecodingError.typeMismatch(JSONType.self,
                        DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "unsupported json format type"))
        }
    }
}

// AnyJSONType 转换至指定的类型
extension AnyJSONType {
    // AnyJSONType -> Bool
    func toValueBool() -> Bool? {
        if let value = self.jsonValue as? Bool {
            return value
        } else if let value = self.jsonValue as? Int {
            if value == 0 {
                return false
            } else {
                return true
            }
        } else if let value = self.jsonValue as? Double {
            if value == 0.0 {
                return false
            }
            return true
        } else {
            return nil
        }
    }
    
    // AnyJSONType -> Int
    func toValueInt() -> Int? {
        if let value = self.jsonValue as? Bool {
            if value == true {
                return 1
            } else {
                return 0
            }
        } else if let value = self.jsonValue as? Int {
            return value
        } else if let value = self.jsonValue as? Double {
            return Int(value)
        } else {
            return nil
        }
    }
    
    func toString() -> String? {
        if let value = self.jsonValue as? String {
            return value
        }
        return nil
    }
    
    // AnyJSONType -> Float
    func toValueFloat() -> Float? {
        if let value = self.jsonValue as? Bool {
            if value == true {
                return 1.0
            } else {
                return 0.0
            }
        } else if let value = self.jsonValue as? Int {
            return Float(value)
        } else if let value = self.jsonValue as? Double {
            return Float(value)
        } else {
            return nil
        }
    }
}





















